//package com.rtf.framework.common.distributed.lock.redis;
//
//import com.rtf.framework.common.distributed.lock.DistributedLock;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang3.StringUtils;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.data.redis.core.StringRedisTemplate;
//import org.springframework.data.redis.core.script.DefaultRedisScript;
//import org.springframework.data.redis.core.script.RedisScript;
//
//import java.nio.charset.StandardCharsets;
//import java.security.MessageDigest;
//import java.util.Collections;
//import java.util.UUID;
//import java.util.concurrent.BrokenBarrierException;
//import java.util.concurrent.CyclicBarrier;
//import java.util.concurrent.ExecutorService;
//import java.util.concurrent.Executors;
//
//@Slf4j
//public class RedisLockServiceTest {
//
//    // Redis获取锁:setnx+设置过期时间的执行命令
//    private final static String LUA_SCRIPT_LOCK = "return redis.call('SET', KEYS[1], ARGV[1], 'NX', 'PX', ARGV[2]) ";
//
//    private static RedisScript<String> scriptLock = new DefaultRedisScript<String>(LUA_SCRIPT_LOCK, String.class);
//
//    //Redis释放锁：通过value判定
//    private static final String LUA_SCRIPT_UNLOCK =
//            "if (redis.call('GET', KEYS[1]) == ARGV[1]) "
//                    + "then return redis.call('DEL',KEYS[1]) "
//                    + "else " + "return 0 " + "end" ;
//
//    private static RedisScript<Long> scriptUnlock = new DefaultRedisScript<Long>(LUA_SCRIPT_UNLOCK, Long.class);
//
//    @Autowired
//    private StringRedisTemplate stringRedisTemplate ;
//
//    public void concurrentTest() {
//        int N = 50 ;
//        ExecutorService executorService = Executors.newCachedThreadPool();
//        CyclicBarrier barrier = new CyclicBarrier(N);
//        for (int i = 0; i < N; i++) {
//            executorService.execute(new doServiceRunnable(barrier));
//        }
//        executorService.shutdown();
//        while (!executorService.isTerminated()) {
//            try {
//                Thread.sleep(10);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//        }
//        System.out.println("所有线程执行完毕...");
//    }
//
//
//    private class doServiceRunnable implements Runnable {
//
//        private CyclicBarrier cyclicBarrier;
//
//        public doServiceRunnable(CyclicBarrier cyclicBarrier) {
//            this.cyclicBarrier = cyclicBarrier;
//        }
//
//        @Override
//        public void run() {
//            System.out.println("线程" + Thread.currentThread().getName() + "正在写入数据...");
//            try {
//                Thread.sleep(3000);      //以睡眠来模拟写入数据操作
//                cyclicBarrier.await();
//
//                System.out.println("线程开始执行逻辑处理时间" + Thread.currentThread().getName() + " " + System.currentTimeMillis());
//                this.doLogic();
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            } catch (BrokenBarrierException e) {
//                e.printStackTrace();
//            }
//        }
//
//        public void doLogic() {
//            boolean lock = false;
//            DistributedLock redisLock = null;
//            String code = "code123456"; //  由一定的规则生成
//            try {
//                redisLock = lock(code);
//                lock = (redisLock != null);
//                if (lock) {//redis锁并发控制
//                    String token = this.generateAccessToken("client_id_123", "client_secret_456");
//
//                    //保存缓存的access_token到redis(授权码已从redis删除，生成的access_token可能因为网络中断或其他原因没传回去，故缓存到redis10分钟)
////                    redisTemplate.opsForValue().set("TEST_TOKEN_" + code, token, 10, TimeUnit.MINUTES);
//                    log.info("返回新的token=" + token);
//                }
//            } catch (Exception e) {
//                throw e;
//            } finally {
//                if (lock) {
//                    //删除redis中的授权码
//                    unlock(redisLock);
//                }
//            }
////            if (!lock) {
////                log.info("获取锁失败");
////            }
//        }
//
//        //获取锁
//        private DistributedLock lock(String code) {
//            //并发标志键值
//            String flagKey = "TEST_REDIS_CONCURRENT_LOCK_" + code;
//            String uuid = UUID.randomUUID().toString() ;
//            //过期时间/毫秒
//            String expireTime = "1000" ;
//            String execute = stringRedisTemplate.execute( scriptLock ,
//                    stringRedisTemplate.getStringSerializer() , stringRedisTemplate.getStringSerializer() ,
//                    Collections.singletonList(flagKey), uuid, expireTime ) ;
//            if (execute != null && execute.equals("OK")) {
//                log.info("线程" + Thread.currentThread().getName() + "===============>获取锁成功,授权码code：" + code);
//                return new DistributedLock(flagKey, uuid);
//            }
//            return null;
//        }
//
//        //释放锁
//        private void unlock(DistributedLock redisLock) {
////            stringRedisTemplate.execute(scriptUnlock, stringRedisTemplate.getStringSerializer(), (RedisSerializer<Long>) stringRedisTemplate.getKeySerializer(),
////                    Collections.singletonList(redisLock.getKey()), redisLock.getValue());
//        }
//
//        /**
//         * 生成唯一AccessToken
//         *
//         * @param client_id
//         * @param client_secret
//         * @return
//         */
//        private String generateAccessToken(String client_id, String client_secret) {
//            String md5Str = md5(client_id + client_secret + System.currentTimeMillis());
//            return md5Str.substring(md5Str.length() - 12, md5Str.length()) + UUID.randomUUID().toString().replace("-", "");
//        }
//
//        /**
//         * 通用md5加密方法
//         *
//         * @param text
//         * @return
//         */
//        private String md5(String text) {
//            if (text == null || StringUtils.isEmpty(text.trim()))
//                return "";
//            try {
//                StringBuilder sb = new StringBuilder();
//                MessageDigest md = MessageDigest.getInstance("MD5");
//                md.update(text.getBytes(StandardCharsets.UTF_8));
//                for (byte b : md.digest()) {
//                    int n = b;
//                    if (n < 0) n += 256;
//                    if (n < 16) sb.append("0");
//                    sb.append(Integer.toHexString(n));
//                }
//                return sb.toString();
//            } catch (Exception e) {
//                log.error(e.getMessage(), e.getCause());
//            }
//            return null;
//        }
//    }
//
//}
